using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using HelixToolkit.Wpf.SharpDX;
using CommunityToolkit.Mvvm.Input;
using HelixToolkit.SharpDX.Core;
using HelixToolkit.Wpf;
using HelixToolkit.Wpf.SharpDX;
using SharpDX;
using Sensor.UI.Models;
using Sensor.UI.Utils;

namespace Sensor.UI.ViewModels;

/// <summary>
/// 渲染ViewModel，负责3D模型控制和渲染
/// </summary>
public partial class RenderViewModel : ViewModelBase, IDisposable
{
    // 3D渲染相关属性
    [ObservableProperty]
    private Point3DCollection _positions = new();

    [ObservableProperty]
    private Int32Collection _triangleIndices = new();

    [ObservableProperty]
    private ColorCollection _colors = new();

    [ObservableProperty]
    private Vector3DCollection _normals = new();

    // 渲染控制属性
    [ObservableProperty]
    private bool _showAxes = true;

    [ObservableProperty]
    private bool _showGrid = true;

    [ObservableProperty]
    private bool _autoRotate = false;

    [ObservableProperty]
    private double _rotationSpeed = 1.0;

    [ObservableProperty]
    private double _scale = 1.0;

    [ObservableProperty]
    private double _pointSize = 5.0;

    [ObservableProperty]
    private Color _pointColor = Colors.Cyan;

    // 相机控制属性
    [ObservableProperty]
    private double _cameraDistance = 10.0;

    [ObservableProperty]
    private double _cameraFieldOfView = 45.0;

    [ObservableProperty]
    private Vector3D _cameraPosition = new(0, 0, 10);

    [ObservableProperty]
    private Vector3D _cameraLookDirection = new(0, 0, -1);

    [ObservableProperty]
    private Vector3D _cameraUpDirection = new(0, 1, 0);

    // 数据源
    private readonly ObservableCollection<SensorInfo> _sensorData = new();

    // 渲染元素集合
    public ObservableCollection<LineGeometryModel3D> LineModels { get; } = new();
    public ObservableCollection<BillboardTextModel3D> TextModels { get; } = new();
    public ObservableCollection<PointGeometryModel3D> PointModels { get; } = new();

    // 渲染状态
    [ObservableProperty]
    private bool _isRendering = false;

    [ObservableProperty]
    private int _pointCount = 0;

    [ObservableProperty]
    private int _frameRate = 0;

    // 渲染计时器
    private System.Windows.Threading.DispatcherTimer? _renderTimer;
    private DateTime _lastFrameTime = DateTime.Now;
    private int _frameCount = 0;

    public RenderViewModel()
    {
        InitializeRenderer();
    }

    /// <summary>
    /// 初始化渲染器
    /// </summary>
    private void InitializeRenderer()
    {
        // 初始化渲染计时器
        _renderTimer = new System.Windows.Threading.DispatcherTimer
        {
            Interval = TimeSpan.FromMilliseconds(16) // 约60 FPS
        };
        _renderTimer.Tick += OnRenderTimerTick;
        _renderTimer.Start();

        // 初始化默认点云
        InitializeDefaultPointCloud();
    }

    /// <summary>
    /// 初始化默认点云
    /// </summary>
    private void InitializeDefaultPointCloud()
    {
        // 创建一个简单的示例点云
        var positions = new Point3DCollection();
        var colors = new ColorCollection();
        var normals = new Vector3DCollection();

        // 创建一个简单的立方体点云
        for (int x = -5; x <= 5; x++)
        {
            for (int y = -5; y <= 5; y++)
            {
                for (int z = -5; z <= 5; z++)
                {
                    positions.Add(new Point3D(x * 0.1, y * 0.1, z * 0.1));
                    
                    // 根据位置设置颜色
                    var color = Color.FromArgb(
                        255,
                        (byte)(128 + x * 12),
                        (byte)(128 + y * 12),
                        (byte)(128 + z * 12));
                    colors.Add(color);
                    
                    normals.Add(new Vector3D(0, 0, 1));
                }
            }
        }

        Positions = positions;
        Colors = colors;
        Normals = normals;
        PointCount = positions.Count;
    }

    /// <summary>
    /// 添加传感器数据
    /// </summary>
    public void AddSensorData(SensorInfo sensorInfo)
    {
        App.Current.Dispatcher.Invoke(() =>
        {
            _sensorData.Add(sensorInfo);
            UpdatePointCloud();
        });
    }

    /// <summary>
    /// 更新点云数据
    /// </summary>
    private void UpdatePointCloud()
    {
        if (_sensorData.Count == 0) return;

        var positions = new Point3DCollection();
        var colors = new ColorCollection();
        var normals = new Vector3DCollection();

        // 处理传感器数据为点云
        foreach (var sensor in _sensorData)
        {
            // 将传感器数据转换为3D坐标
            var point = ConvertSensorDataToPoint3D(sensor);
            positions.Add(point);

            // 根据传感器值设置颜色
            var color = GetColorFromSensorValue(sensor);
            colors.Add(color);

            // 设置法线
            normals.Add(new Vector3D(0, 0, 1));
        }

        // 添加箭头表示方向
        AddArrows(positions, colors);

        // 应用力场凹陷效果
        ApplyForceFieldEffect(positions, colors);

        Positions = positions;
        Colors = colors;
        Normals = normals;
        PointCount = positions.Count;
    }

    /// <summary>
    /// 将传感器数据转换为3D点
    /// </summary>
    private Point3D ConvertSensorDataToPoint3D(SensorInfo sensor)
    {
        // 根据传感器数据的类型和值转换为3D坐标
        // 这里使用简单的映射，实际应用中需要根据传感器特性调整
        double x = sensor.X * Scale;
        double y = sensor.Y * Scale;
        double z = sensor.Z * Scale;

        return new Point3D(x, y, z);
    }

    /// <summary>
    /// 根据传感器值获取颜色
    /// </summary>
    private Color GetColorFromSensorValue(SensorInfo sensor)
    {
        // 根据传感器值映射到颜色
        // 这里使用简单的线性映射，可以根据需要调整
        double normalizedValue = (sensor.Value + 100) / 200.0; // 假设值范围是-100到100
        normalizedValue = Math.Max(0, Math.Min(1, normalizedValue));

        // 从蓝色到红色的渐变
        byte r = (byte)(normalizedValue * 255);
        byte g = (byte)((1 - Math.Abs(normalizedValue - 0.5) * 2) * 255);
        byte b = (byte)((1 - normalizedValue) * 255);

        return Color.FromArgb(255, r, g, b);
    }

    /// <summary>
    /// 添加箭头表示方向
    /// </summary>
    private void AddArrows(Point3DCollection positions, ColorCollection colors)
    {
        // 为每个点添加箭头表示方向
        for (int i = 0; i < positions.Count; i++)
        {
            var point = positions[i];
            var direction = new Vector3D(0, 0, 1); // 默认向上

            // 创建箭头
            var arrowLength = 0.5 * Scale;
            var arrowEnd = new Point3D(
                point.X + direction.X * arrowLength,
                point.Y + direction.Y * arrowLength,
                point.Z + direction.Z * arrowLength);

            // 添加箭头线
            var lineModel = new LineGeometryModel3D
            {
                Points = new Point3DCollection { point, arrowEnd },
                Color = colors[i],
                Thickness = 2
            };
            LineModels.Add(lineModel);
        }
    }

    /// <summary>
    /// 应用力场凹陷效果
    /// </summary>
    private void ApplyForceFieldEffect(Point3DCollection positions, ColorCollection colors)
    {
        if (positions.Count == 0) return;

        // 计算中心点
        var centerX = positions.Average(p => p.X);
        var centerY = positions.Average(p => p.Y);
        var centerZ = positions.Average(p => p.Z);
        var center = new Point3D(centerX, centerY, centerZ);

        // 应用力场效果
        for (int i = 0; i < positions.Count; i++)
        {
            var point = positions[i];
            var toCenter = new Vector3D(
                center.X - point.X,
                center.Y - point.Y,
                center.Z - point.Z);

            var distance = toCenter.Length;
            if (distance < 0.001) continue; // 避免除零

            // 归一化方向向量
            toCenter.Normalize();

            // 计算力场强度（距离越近，力越强）
            var forceStrength = Math.Max(0, 1 - distance / (5 * Scale));
            forceStrength = forceStrength * forceStrength; // 平方衰减

            // 应用力场偏移
            var offset = toCenter * forceStrength * 0.2 * Scale;
            positions[i] = new Point3D(
                point.X + offset.X,
                point.Y + offset.Y,
                point.Z + offset.Z);

            // 调整颜色以反映力场影响
            var color = colors[i];
            var r = Math.Min(255, color.R + (byte)(forceStrength * 50));
            var g = Math.Max(0, color.G - (byte)(forceStrength * 30));
            var b = Math.Max(0, color.B - (byte)(forceStrength * 30));
            colors[i] = Color.FromArgb(color.A, (byte)r, (byte)g, (byte)b);
        }
    }

    /// <summary>
    /// 渲染计时器事件处理
    /// </summary>
    private void OnRenderTimerTick(object? sender, EventArgs e)
    {
        // 计算帧率
        _frameCount++;
        var now = DateTime.Now;
        if ((now - _lastFrameTime).TotalSeconds >= 1.0)
        {
            FrameRate = _frameCount;
            _frameCount = 0;
            _lastFrameTime = now;
        }

        // 自动旋转
        if (AutoRotate)
        {
            // 更新相机位置以实现旋转
            var angle = RotationSpeed * 0.01;
            var cos = Math.Cos(angle);
            var sin = Math.Sin(angle);

            var newX = CameraPosition.X * cos - CameraPosition.Z * sin;
            var newZ = CameraPosition.X * sin + CameraPosition.Z * cos;

            CameraPosition = new Vector3D(newX, CameraPosition.Y, newZ);
            CameraLookDirection = new Vector3D(-newX, -CameraPosition.Y, -newZ);
        }

        IsRendering = true;
    }

    /// <summary>
    /// 重置视图
    /// </summary>
    [RelayCommand]
    private void ResetView()
    {
        CameraPosition = new Vector3D(0, 0, 10);
        CameraLookDirection = new Vector3D(0, 0, -1);
        CameraUpDirection = new Vector3D(0, 1, 0);
        Scale = 1.0;
        AutoRotate = false;
    }

    /// <summary>
    /// 清空点云数据
    /// </summary>
    [RelayCommand]
    private void ClearPointCloud()
    {
        App.Current.Dispatcher.Invoke(() =>
        {
            _sensorData.Clear();
            Positions.Clear();
            Colors.Clear();
            Normals.Clear();
            TriangleIndices.Clear();
            LineModels.Clear();
            TextModels.Clear();
            PointModels.Clear();
            PointCount = 0;
        });
    }

    /// <summary>
    /// 保存点云数据
    /// </summary>
    [RelayCommand]
    private async Task SavePointCloudAsync()
    {
        try
        {
            var saveFileDialog = new Microsoft.Win32.SaveFileDialog
            {
                Filter = "点云文件 (*.ply)|*.ply|点云文件 (*.pcd)|*.pcd|所有文件 (*.*)|*.*",
                DefaultExt = ".ply",
                FileName = $"PointCloud_{DateTime.Now:yyyyMMdd_HHmmss}.ply"
            };

            if (saveFileDialog.ShowDialog() == true)
            {
                // 这里可以实现点云数据保存逻辑
                // 例如保存为PLY或PCD格式
                AddInfo($"点云数据已保存到: {saveFileDialog.FileName}");
            }
        }
        catch (Exception ex)
        {
            AddError($"保存点云数据失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 添加信息日志（用于与LogViewModel交互）
    /// </summary>
    private void AddInfo(string message)
    {
        // 这里可以通过事件或依赖注入与LogViewModel交互
        // 例如：LogViewModel?.AddInfo(message);
    }

    /// <summary>
    /// 添加错误日志（用于与LogViewModel交互）
    /// </summary>
    private void AddError(string message)
    {
        // 这里可以通过事件或依赖注入与LogViewModel交互
        // 例如：LogViewModel?.AddError(message);
    }

    #region 资源释放
    private bool _disposedValue = false;

    /// <summary>
    /// 释放资源
    /// </summary>
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                // 停止渲染计时器
                _renderTimer?.Stop();
                _renderTimer = null;

                // 清理集合
                Positions?.Clear();
                Colors?.Clear();
                Normals?.Clear();
                TriangleIndices?.Clear();
                LineModels?.Clear();
                TextModels?.Clear();
                PointModels?.Clear();
                _sensorData?.Clear();
            }

            _disposedValue = true;
        }
    }

    /// <summary>
    /// 析构函数
    /// </summary>
    ~RenderViewModel()
    {
        Dispose(false);
    }

    /// <summary>
    /// 实现IDisposable接口
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}